package com.thirdguardian.sign.signv1;

import com.thirdguardian.sign.comm.CommUtils;
import com.thirdguardian.sign.comm.ConstStr;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

/**
 * @author Administrator
 * @Classname SignUtil
 * @Description 签名算法
 * @Date 2021/3/25 22:15
 */
public class SignUtils {


    /**
     * RSA密钥对对象
     */
    public static class LicensePair {

        private final String appId;
        private final String secretKey;

        public LicensePair(String appId, String secretKey) {
            this.appId = appId;
            this.secretKey = secretKey;
        }

        public String getAppId() {
            return appId;
        }

        public String getSecretKey() {
            return secretKey;
        }

    }

    /**
     * 签名方式
     *
     * @author Administrator
     */
    public enum SignType {
        /**
         * HMAC-SHA256 加密
         */
        HMACSHA256("HMAC-SHA256"),
        /**
         * MD5 加密
         */
        MD5("MD5");

        SignType(String type) {
            this.type = type;
        }

        private final String type;

        public String getType() {
            return type;
        }

        @Override
        public String toString() {
            return type;
        }

        public static SignType fromString(String text) {
            for (SignType b : SignType.values()) {
                if (b.type.equalsIgnoreCase(text)) {
                    return b;
                }
            }
            return null;
        }
    }

    /**
     * 生成包含签名的参数
     *
     * @param params
     * @param license
     * @param signMethod
     * @return
     */
    public static Map<String, Object> singRequestParams(Map<String, Object> params, LicensePair license, SignUtils.SignType signMethod) {
        DateFormat df = new SimpleDateFormat(ConstStr.TIME_FORMAT_STR);
        params.put(ConstStr.TIMESTAMP, df.format(new Date()));
        params.put(ConstStr.NONCE_STR, CommUtils.generateStr());
        params.put(ConstStr.APP_ID, license.getAppId());
        return WxPaySignKit.buildSign(params, license.getSecretKey(), signMethod);
    }


    /**
     * 验证签名
     *
     * @param params
     * @param license
     * @return
     * @throws IOException
     */
    public static boolean verifySign(Map<String, Object> params, LicensePair license) throws Exception {
        try {
            DateFormat df = new SimpleDateFormat(ConstStr.TIME_FORMAT_STR);
            params.put(ConstStr.TIMESTAMP, df.format(params.get(ConstStr.TIMESTAMP)));
        } catch (Exception e) {
            params.put(ConstStr.TIMESTAMP, params.get(ConstStr.TIMESTAMP));
        }
        // 校验签名的时间
        verifyTimeStr((String) params.get(ConstStr.TIMESTAMP));
        return WxPaySignKit.verifyNotify(params, license.getSecretKey());
    }

    private static void verifyTimeStr(String timeStr) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat(ConstStr.TIME_FORMAT_STR);
        Date date = sdf.parse(timeStr);
        Calendar beforeTime = Calendar.getInstance();
        beforeTime.add(Calendar.MINUTE, -10);
        Calendar afterTime = Calendar.getInstance();
        afterTime.add(Calendar.MINUTE, 10);
        if (date.after(afterTime.getTime()) || date.before(beforeTime.getTime())) {
            throw new Exception("签名时间错误");
        }

    }
}
